#ifdef ASAN_REPORT_STUB

#include "asan_stubs.h"
#include "asan_internal_defs.h"
#include "asan_shadow_memory.h"
#include "asan_mapping.h"
#include "asan_utils.h"
#include "stdio.h"

using namespace __sanitizer;

extern "C" {

void printf_shadow_bytes(uptr addr) {
  Printf("Shadow range [%llx, %llx]\n\n", ASAN_SHADOW_OFFSET, ASAN_SHADOW_END);
  uptr saddr = MEM_TO_SHADOW(addr);
  int row_bytes = 8;
  uptr print_beg_saddr = RoundDownTo(saddr, row_bytes) - row_bytes;
  uptr print_end_saddr = RoundUpTo(saddr, row_bytes) + row_bytes - 1;
  print_beg_saddr = Max<uptr>(ASAN_SHADOW_OFFSET, print_beg_saddr);
  print_end_saddr = Min<uptr>(ASAN_SHADOW_END, print_end_saddr);
  for (uptr beg = print_beg_saddr; beg <= print_end_saddr; beg += row_bytes) {
    Printf("0x%llx: ", beg);
    for (uptr offset = 0; offset  < row_bytes; ++offset) {
      su_t * to_print_saddr = (su_t*)(beg + offset);
      if (beg + offset == saddr)
        Printf(" [%x] ", (*to_print_saddr) & 0x0ff);
      else
        Printf("  %x  ", (*to_print_saddr) & 0x0ff);
    }
    Printf("\n");
  }
}

INTERFACE_ATTRIBUTE void __asan_report_load1(uptr addr) {
  Printf("__asan_report_load1\n");
  printf_shadow_bytes(addr);
  Die();
}

INTERFACE_ATTRIBUTE void __asan_report_load2(uptr addr) {
  Printf("__asan_report_load2\n");
  printf_shadow_bytes(addr);
  Die();
}

INTERFACE_ATTRIBUTE void __asan_report_load4(uptr addr) {
  Printf("__asan_report_load4\n");
  printf_shadow_bytes(addr);
  Die();
}

INTERFACE_ATTRIBUTE void __asan_report_load8(uptr addr) {
  Printf("__asan_report_load8\n");
  printf_shadow_bytes(addr);
  Die();
}

INTERFACE_ATTRIBUTE void __asan_report_load16(uptr addr) {
  Printf("__asan_report_load16\n");
  printf_shadow_bytes(addr);
  Die();
}

}

#endif // ASAN_REPORT_STUB